using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;

using Athena.Core;

namespace Athena.Objects
{
    [Serializable()]
    public class TerminatorGlyph : PartGlyph
    {

        public TerminatorGlyph(PointF location)
        {
            TextH = HorizontalAlignment.Center;
            TextV = VerticalAlignment.BelowBottom;
            _Location = location;
            _Dimensions = new SizeF(60, 46);

            _oFillColorStart = Color.White;
            _oFillColorEnd = Color.SteelBlue;
            _oPartColor = Color.Red;
            _oEdgeColor = Color.Black;

            Item =new Terminator("Terminator_0", "AAAACCGTTGATTAAAAAAAAA");
            //ItemPtr.Drawable = this;
            
        }
        public TerminatorGlyph() 
        {
            TextH = HorizontalAlignment.Center;
            TextV = VerticalAlignment.BelowBottom;
            _Location = new PointF(0, 0);
            _Dimensions = new SizeF(20, 20);
            Name = "Terminator_0";
            
            _oPartColor = Color.Red;
            _oEdgeColor = Color.Black;
            _Item = new Terminator();
        }

        public override Bitmap GetPreview(int width, int height)
        {
            Bitmap oBitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(oBitmap);

            RenderIcon(g, width, height);

            return oBitmap;
        }

        public override void RenderIcon(Graphics g, float width, float height)
        {
            Pen oOutline = new Pen(_oEdgeColor, 0.5f);

            Brush oFilled = new SolidBrush(_oPartColor);

            GraphicsPath oPath = (GraphicsPath)_oBlockPath.Clone();// CreatePath();
            GraphicsPath oPathShine = (GraphicsPath)_oPathShine.Clone();// ShiningLine();

            RectangleF pathBounds = oPath.GetBounds();

            Matrix oTransform = new Matrix();

            float sz = Math.Min(width, height);

            oTransform.Scale(
                   0.7f * sz / pathBounds.Width,
                   0.7f * sz / pathBounds.Height, MatrixOrder.Prepend);
            oTransform.Translate(0.15f * width, 0.15f * height);

            oPath.Transform(oTransform);
            oPathShine.Transform(oTransform);

            g.FillPath(oFilled, oPath);
            g.DrawPath(oOutline, oPath);
            g.DrawPath(new Pen(Color.White, sz / 20), oPathShine);

        }

        static GraphicsPath _oBlockPath = Utility.CreateBlockPath(), _oPathShine = ShiningLine();

        static GraphicsPath CreateSchematicPath(float w, float h)
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddLine(0f, h, w/3, h);
            /*oPath.AddLine(w/3, h, w/2, 0.8f*h);            
            oPath.AddLine(w/3, h, w, h);*/
            oPath.CloseFigure();

            return oPath;
        }


        public override SBMLExtension.EmlRenderExtension.LocalStyle ToStyle(SBMLExtension.EmlRenderExtension.RenderInformation oInfo)
        {

            SBMLExtension.EmlRenderExtension.LocalStyle oResult = new SBMLExtension.EmlRenderExtension.LocalStyle();
            SBMLExtension.EmlRenderExtension.Group oGroup = new SBMLExtension.EmlRenderExtension.Group();
            oGroup.Stroke = oInfo.AddColorDefinition(_oEdgeColor);
            oGroup.StrokeWidth = _dEdgeThickness.ToString();
            if (_oFillColorStart == _oFillColorEnd)
                oGroup.Fill = oInfo.AddColorDefinition(_oFillColorStart);
            else
                oGroup.Fill = oInfo.AddLinearGradientDefinition(_oFillColorStart, _oFillColorEnd);


            oGroup.Children.Add(new SBMLExtension.EmlRenderExtension.Rectangle());

            SBMLExtension.EmlRenderExtension.Polygon oPolygon = new SBMLExtension.EmlRenderExtension.Polygon();
            oPolygon.Fill = oInfo.AddColorDefinition(PartColor);            
            oPolygon.Stroke = oGroup.Stroke;
            oPolygon.StrokeWidth = oGroup.StrokeWidth;

            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(0f, 3.5f ),
                new SBMLExtension.LayoutExtension.Point(3.5f, 0)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(3.5f, 0f),
                new SBMLExtension.LayoutExtension.Point(8.5f, 0f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(8.5f, 0f),
                new SBMLExtension.LayoutExtension.Point(12f, 3.5f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(12f, 3.5f),
                new SBMLExtension.LayoutExtension.Point(12f, 8.5f)
                ));            
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(12f, 8.5f),
                new SBMLExtension.LayoutExtension.Point(8.5f, 12f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(8.5f, 12f),
                new SBMLExtension.LayoutExtension.Point(3.5f, 12f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(3.5f, 12f),
                new SBMLExtension.LayoutExtension.Point(0f, 8.5f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(0f, 8.5f),
                new SBMLExtension.LayoutExtension.Point(0f, 3.5f)
                ));

            float dScaleX = 0.45f * _Dimensions.Width / 12f;
            float dScaleY = 0.45f * _Dimensions.Height / 12f;

            float dOffsetX = 0.5f * _Dimensions.Width - 12f * dScaleX / 2;
            float dOffsetY = 0.5f * _Dimensions.Height - 12f * dScaleY / 2;

            oPolygon.Transform = dScaleX.ToString() +  ",0,0," + dScaleY.ToString() + "," + dOffsetX.ToString() + "," + dOffsetY.ToString();

            oGroup.Children.Add(oPolygon);


            if (!string.IsNullOrEmpty(Text) && ShowText)
            {
                SBMLExtension.EmlRenderExtension.Text oText = new SBMLExtension.EmlRenderExtension.Text();
                oText.FontFamily = TextFont.FontFamily.Name;
                oText.FontSize = TextFont.SizeInPoints.ToString();
                oText.Stroke = oInfo.AddColorDefinition(TextColor);
                if (TextFont.Bold) oText.FontWeight = SBMLExtension.EmlRenderExtension.Text.FontWeiths.bold.ToString();
                if (TextFont.Italic) oText.FontStyle = SBMLExtension.EmlRenderExtension.Text.FontStyles.italic.ToString();
                oText.StrokeWidth = "1";
                oText.Y = "130%";
                oText.X = "-50%";
                oText.TheText = Text;
                oGroup.Children.Add(oText);
            }
            oResult.Group = oGroup;
            return oResult;
        }

       

        static GraphicsPath ShiningLine()
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddLine(1.2f, 6.5f, 1.2f, 3.8f);
            oPath.AddLine(1.2f, 3.8f, 3.8f, 1.2f);
            oPath.AddLine(3.8f, 1.2f, 6.5f, 1.2f);              

            //oPath.CloseFigure();

            return oPath;
        }

        public override bool HasPreview
        {
            get
            {
                return true;
            }
        }

        public override void RenderGlyph(System.Drawing.Graphics g)
        {
            Pen oOutline = new Pen(_oEdgeColor, _dEdgeThickness);

            Brush oFilled = new SolidBrush(_oPartColor);

            GraphicsPath oPath;            
            float w, h;

            switch (View)
            {
                case ViewType.Schematic:
                    w = _Dimensions.Width;
                    h = _Dimensions.Height;
                    oPath = (GraphicsPath)CreateSchematicPath(w+5, h);                    
                    break;
                default:
                    DrawBox(g);
                    oPath = (GraphicsPath)_oBlockPath.Clone();
                    w = h = 0.45f * Math.Min(_Dimensions.Height, _Dimensions.Width);

                    break;
            }

            RectangleF pathBounds = oPath.GetBounds();

            Matrix oTransform = new Matrix();

            if (Direction == Part.Orientation.forward)
            {
                if (View != ViewType.Schematic)
                {
                    oTransform.Scale(
                         w / pathBounds.Width,
                         h / pathBounds.Height, MatrixOrder.Prepend);
                }
                oTransform.Translate(
                    0.5f * _Dimensions.Width + _Location.X - w / 2,
                    0.5f * _Dimensions.Height + _Location.Y - h / 2,
                    MatrixOrder.Append);
            }
            else
            {
                if (View != ViewType.Schematic)
                {
                    oTransform.Scale(
                       -w / pathBounds.Width,
                         h / pathBounds.Height, MatrixOrder.Prepend);
                }
                else
                {
                    oTransform.Scale(-1, 1, MatrixOrder.Prepend);
                }
                oTransform.Translate(
                    0.5f * _Dimensions.Width + _Location.X + w / 2,
                    0.5f * _Dimensions.Height + _Location.Y - h/2,
                    MatrixOrder.Append);
            }

            oPath.Transform(oTransform);
            g.DrawPath(oOutline, oPath);

            if (View == ViewType.Block)
            {
                GraphicsPath oPathShine = (GraphicsPath)_oPathShine.Clone();
                oPathShine.Transform(oTransform);

                g.FillPath(oFilled, oPath);
                g.DrawPath(new Pen(Color.White, w / 20), oPathShine);

                /*oTransform = new Matrix();
                oTransform.Scale(-w, -h);
                oPathShine.Transform(oTransform);
                g.DrawPath(new Pen(Color.Gray, w / 10), oPathShine);*/
            }
        }

        
    }
}
